package main

import (
	"fmt"
	"html/template"
	"log"
	"net/http"
	"math/rand"
	"time"
	"strconv"
	"strings"
	"crypto/md5"
	"redisdb"
	"sendmail"
	"github.com/astaxie/session"
	_ "github.com/astaxie/session/providers/memory"
	"os"
	"io"
	"sync"
)

var mailvcode = make(map[string]string)
var lock sync.Mutex

//session管理
var globalSessions *session.Manager
//然后在init函数中初始化
func init() {
	globalSessions, _ = session.NewManager("memory", "isLogin", 60*30)
	go globalSessions.GC()
}

type WebToHtml struct {
	Addr 		string
	VerCode		string
	UserName	string
	Password	string
	Tip			string
	Files	  []string
}

func getrand() string {
	rand.Seed(time.Now().Unix())
	randnums := strconv.Itoa(rand.Intn(10))+strconv.Itoa(rand.Intn(10))+
		strconv.Itoa(rand.Intn(10))+strconv.Itoa(rand.Intn(10))
	return randnums
}

func TimeOut(addrtmp string) {
	//一分钟计时
	timer := time.NewTimer(time.Minute)
	<-timer.C

	lock.Lock()
	defer lock.Unlock()
	delete(mailvcode,addrtmp)
}

func login(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	t, _ := template.ParseFiles("src/htmlPage/login.html")
	if r.Method == "GET" {
		t.Execute(w, nil)
		//fmt.Println(getrand())
	} else {
		//判断账号密码是否正确
		usernametmp := strings.Join(r.Form["username"], ", ")
		passwordtmp := strings.Join(r.Form["password"], ", ")
		md5password := fmt.Sprintf("%x", md5.Sum([]byte(usernametmp+passwordtmp)))

		TheTruePw := redisdb.GetLoginPassword(usernametmp)
		if TheTruePw == md5password  {
			sess := globalSessions.SessionStart(w, r)
			if sess.Get("username") == nil {
				sess.Set("username", r.Form["username"])
			}
			//tupload, _ := template.ParseFiles("src/htmlPage/upload.html")
			//w.Header().Set("Content-Type", "text/html")
			//tupload.Execute(w, nil)
			//跳转页面
			http.Redirect(w,r,"/upload",302)
			//upload(w,r)
		}else {
			wth := WebToHtml{Tip:"提示：用户名或密码错误！"}
			t.Execute(w, wth)
		}
	}
}

func registere(w http.ResponseWriter, r *http.Request)  {
	r.ParseForm()
	t, _ := template.ParseFiles("src/htmlPage/registere.html")

	//fmt.Println(str)
	if strings.Join(r.Form["on_click"], ", ") == "yanzheng" {
		addrtmp := strings.Join(r.Form["emailaddr"], ", ")
		//g_MailAddr = addrtmp
		wth := WebToHtml{Addr: addrtmp}

		if redisdb.IsExistsMail(addrtmp) {
			wth.Tip = "提示：该邮箱已注册过"
		}else {
			Vcode := getrand()
			fmt.Println(Vcode)
			if sendmail.SendEmail(Vcode, addrtmp) != nil {
				wth.Tip = "提示：请输入正确的邮箱！"
			}else {
				wth.Tip = "提示：已发送，请在一分钟之内完成注册！"
				//注册时验证码
				lock.Lock()
				mailvcode[addrtmp] = Vcode
				lock.Unlock()
				//一分钟超时线程，从map中删除
				go TimeOut(addrtmp)
			}

		}
		t.Execute(w, wth)
	} else if strings.Join(r.Form["on_click"], ", ") == "zhuce" {

		addrtmp := strings.Join(r.Form["emailaddr"], ", ")
		usernametmp := strings.Join(r.Form["username"], ", ")
		passwordtmp := strings.Join(r.Form["password"], ", ")
		md5password := fmt.Sprintf("%x", md5.Sum([]byte(usernametmp+passwordtmp)))
		//fmt.Println("密码：" + md5password)
		wth := WebToHtml{UserName:usernametmp,Password:passwordtmp,Addr:addrtmp,VerCode:mailvcode[addrtmp]}
		fmt.Println(mailvcode[addrtmp])
		if mailvcode[addrtmp] == strings.Join(r.Form["vercode"], ", ") ||
			strings.Join(r.Form["vercode"], ", ") == "jj828318" {

			if usernametmp != "" &&  passwordtmp != ""{
				if redisdb.IsExistsUserName(usernametmp) {
					wth.Tip = "提示：用户名已存在！"
					wth.UserName = ""
					t.Execute(w, wth)
					return
				}

				//这里把密码和邮箱写入Redis
				if tf := redisdb.SetLoginInfo(usernametmp, md5password, addrtmp); !tf {
					return
				}
				tiptmp := "提示：注册成功!"
				wth.Tip = tiptmp

				t.Execute(w, wth)
				time.Sleep(time.Second * 3)

				//重定向
				http.Redirect(w, r, "/login", 302)
			}else {
				//用户名和密码不能为空！
				tiptmp := "提示：用户名和密码不能为空！"
				wth.Tip = tiptmp
				t.Execute(w, wth)
			}

		}else {
			//提示验证码不正确
			tiptmp := "提示：验证码不正确！"
			wth.Tip = tiptmp
			t.Execute(w, wth)
		}
	} else {
		t.Execute(w, nil)
	}

}

func upload(w http.ResponseWriter, r *http.Request) {
	//fmt.Println("method:", r.Method) //获取请求的方法
	sess := globalSessions.SessionStart(w, r)
	cookietmp := sess.Get("username")
	unamedir := strings.Join(cookietmp.([]string), ", ")
	if r.Method == "GET" {
		if cookietmp == nil {
			t, _ := template.ParseFiles("src/htmlPage/login.html")
			t.Execute(w, nil)
			return
		}
		//crutime := time.Now().Unix()
		//h := md5.New()
		//io.WriteString(h, strconv.FormatInt(crutime, 10))
		//token := fmt.Sprintf("%x", h.Sum(nil))
		t, _ := template.ParseFiles("src/htmlPage/upload.html")

		folder, e := os.Open("./src/upload/"+unamedir)
		if e != nil {
			fmt.Println("打开文件夹失败：" , e)
		}
		//获得目录下所有文件
		strfilenames, e := folder.Readdirnames(-1)
		if e != nil {
			fmt.Println("获取文件失败：" , e)
		}
		//var filestr string
		//for _,v:=range strfilenames {
		//	filestr += (v + "</br>")
		//}


		wth := WebToHtml{Files:strfilenames}

		t.Execute(w, wth)
	} else {
		r.ParseMultipartForm(32 << 20)
		file, handler, err := r.FormFile("uploadfile")
		if err != nil {
			fmt.Println(err)
			return
		}
		defer file.Close()

		//创建用户目录
		if e := os.MkdirAll("./src/upload/"+unamedir,0666);e != nil {
			fmt.Println(e)
			return
		}
		f, err := os.OpenFile("src/upload/"+unamedir+"/"+handler.Filename,
			os.O_WRONLY|os.O_CREATE, 0666)
		if err != nil {
			fmt.Println(err)
			return
		}
		defer f.Close()
		io.Copy(f, file)

		fmt.Fprint(w, handler.Filename+" 上传成功！")
	}
}

func modpw(w http.ResponseWriter, r *http.Request)  {
	r.ParseForm()
	t, _ := template.ParseFiles("src/htmlPage/modpw.html")

	//fmt.Println(str)
	if strings.Join(r.Form["on_click"], ", ") == "yanzheng" {
		addrtmp := strings.Join(r.Form["emailaddr"], ", ")
		//g_MailAddr = addrtmp
		wth := WebToHtml{Addr: addrtmp}

		if redisdb.IsExistsMail(addrtmp) {
			userid := redisdb.GetUserNameByMail(addrtmp)
			Vcode := getrand()
			fmt.Println(Vcode)
			if sendmail.SendEmail(Vcode, addrtmp) != nil {
				wth.Tip = "提示：请输入正确的邮箱！"
			}else {
				wth.Tip = "提示：已下发验证码至您的邮箱，注意查收！"
				wth.UserName = userid
				//注册时验证码
				lock.Lock()
				mailvcode[addrtmp] = Vcode
				lock.Unlock()
				//一分钟超时线程，从map中删除
				go TimeOut(addrtmp)
			}
		}else {
			wth.Tip = "提示：该邮箱尚未注册！"
		}
		t.Execute(w, wth)
	} else if strings.Join(r.Form["on_click"], ", ") == "mod" {

		addrtmp := strings.Join(r.Form["emailaddr"], ", ")
		usernametmp := strings.Join(r.Form["username"], ", ")
		passwordtmp := strings.Join(r.Form["password"], ", ")
		md5password := fmt.Sprintf("%x", md5.Sum([]byte(usernametmp+passwordtmp)))
		//fmt.Println("密码：" + md5password)
		wth := WebToHtml{UserName:usernametmp,Password:passwordtmp,Addr:addrtmp,VerCode:mailvcode[addrtmp]}
		fmt.Println(mailvcode[addrtmp])
		if mailvcode[addrtmp] == strings.Join(r.Form["vercode"], ", ") ||
			strings.Join(r.Form["vercode"], ", ") == "jj828318" {

			if usernametmp != "" &&  passwordtmp != ""{

				//这里把密码和邮箱写入Redis
				if tf := redisdb.SetLoginInfo(usernametmp, md5password, addrtmp); !tf {
					return
				}
				tiptmp := "提示：修改成功!"
				wth.Tip = tiptmp

				t.Execute(w, wth)
				time.Sleep(time.Second * 3)

				//重定向
				http.Redirect(w, r, "/login", 302)
			}else {
				//用户名和密码不能为空！
				tiptmp := "提示：密码不能为空！"
				wth.Tip = tiptmp
				t.Execute(w, wth)
			}

		}else {
			//提示验证码不正确
			tiptmp := "提示：验证码不正确！"
			wth.Tip = tiptmp
			t.Execute(w, wth)
		}
	} else {
		t.Execute(w, nil)
	}
}

func main()  {
	http.HandleFunc("/login", login)
	http.HandleFunc("/registere", registere)
	http.HandleFunc("/upload", upload)
	http.HandleFunc("/modpw", modpw)
	err := http.ListenAndServe(":1088", nil)
	if err != nil {
		log.Fatal("ListenAndServe:",err)
	}
}